﻿using System;
using Microsoft.Xna.Framework;

namespace GameLibrary
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public sealed class FPS : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private float _fps;
        private const float UpdateInterval = 1.0f;
        private float _timeSinceLastUpdate = 0.0f;
        private float _framecount = 0;

        /// <summary>
        /// Creates a new instance of DrawableGameComponent.
        /// </summary>
        /// <param name="game">The Game that the game component should be attached to.</param>
        /// <remarks></remarks>
        public FPS(Game game)
            : this(game, false, false, game.TargetElapsedTime) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="FPS"/> class.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="synchWithVerticalRetrace">if set to <c>true</c> [synch with vertical retrace].</param>
        /// <param name="isFixedTimeStep">if set to <c>true</c> [is fixed time step].</param>
        /// <param name="targetElapsedTime">The target elapsed time.</param>
        /// <remarks></remarks>
        public FPS(Game game, bool synchWithVerticalRetrace,
                   bool isFixedTimeStep, TimeSpan targetElapsedTime)
            : base(game)
        {
            GraphicsDeviceManager graphics =
                (GraphicsDeviceManager)Game.Services.GetService(
                typeof(IGraphicsDeviceManager));
            graphics.SynchronizeWithVerticalRetrace = synchWithVerticalRetrace;
            Game.IsFixedTimeStep = isFixedTimeStep;
            Game.TargetElapsedTime = targetElapsedTime;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public sealed override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public sealed override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            base.Update(gameTime);
        }

        /// <summary>
        /// Called when the DrawableGameComponent needs to be drawn. Override this method with component-specific drawing code. Reference page contains links to related conceptual articles.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Draw.</param>
        /// <remarks></remarks>
        public sealed override void Draw(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            _framecount++;
            _timeSinceLastUpdate += elapsed;
            if (_timeSinceLastUpdate > UpdateInterval)
            {
                _fps = _framecount / _timeSinceLastUpdate;

#if XBOX360
                System.Diagnostics.Debug.WriteLine("FPS: " + _fps.ToString());
#else
                Game.Window.Title = "FPS: " + _fps;
#endif
                _framecount = 0;
                _timeSinceLastUpdate -= UpdateInterval;
            }

            base.Draw(gameTime);
        }
    }
}